package tech.aichan.AiQA.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.data.domain.*;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import tech.aichan.AiQA.common.ErrorCode;
import tech.aichan.AiQA.esrepo.AppESRepo;
import tech.aichan.AiQA.exception.ThrowUtils;
import tech.aichan.AiQA.mapper.AppMapper;
import tech.aichan.AiQA.mapper.UserMapper;
import tech.aichan.AiQA.model.dto.app.AppAddRequest;
import tech.aichan.AiQA.model.dto.app.AppEditRequest;
import tech.aichan.AiQA.model.dto.app.AppUpdateRequest;
import tech.aichan.AiQA.model.entity.App;
import tech.aichan.AiQA.model.entity.User;
import tech.aichan.AiQA.model.entity.es.AppES;
import tech.aichan.AiQA.model.vo.UserVO;
import tech.aichan.AiQA.model.vo.app.AppVO;
import tech.aichan.AiQA.service.AppService;
import org.springframework.stereotype.Service;
import tech.aichan.AiQA.utils.ESQueryBuilder;
import tech.aichan.AiQA.utils.ESSortBuilder;
import tech.aichan.AiQA.utils.UserInfoUtil;

import java.util.List;
import java.util.Objects;

/**
* @author AiChan
* @description 针对表【app(应用)】的数据库操作Service实现
* @createDate 2024-05-30 14:15:41
*/
@Service
public class AppServiceImpl extends ServiceImpl<AppMapper, App>
    implements AppService{

    @Resource
    private AppMapper appMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private AppESRepo appESRepo;

    @Resource
    private ElasticsearchTemplate elasticsearchTemplate;

    /**
     *
     * @param appAddRequest
     * @return
     */
    @Override
    public Long addApp(AppAddRequest appAddRequest) {
        // 1. 将信息填入App类
        App app = new App();
        BeanUtil.copyProperties(appAddRequest,app);
        // 1.1 用户id
        app.setUserId(UserInfoUtil.getUserId());
        // 2. 判断应用图标是否为空，为空则填入默认图片
        if(StrUtil.isBlankIfStr(app.getAppIcon())){
            // TODO
            app.setAppIcon("https://example.com/default-app-icon.png");
        }
        // 3. 插入数据库
        int insert = appMapper.insert(app);
        ThrowUtils.throwIf(insert != 1, ErrorCode.SYSTEM_ERROR,"保存失败，请重试");
        // 4. 插入ESRepo
        appESRepo.save(AppES.appToAppES(app));
        // 5. 插入Redis TODO
        return app.getId();
    }

    @Override
    public void deleteApp(Long id) {
        // 1. 删除数据库中数据
        int i = appMapper.deleteById(id);
        ThrowUtils.throwIf(i != 1, ErrorCode.SYSTEM_ERROR,"删除失败，请重试");
        // 2. 删除ESRepo中数据
        appESRepo.deleteById(id);
        // 3. 删除Redis中数据 TODO
    }

    @Override
    public Long updateApp(AppUpdateRequest appUpdateRequest) {
        // 1. 将信息填入App类
        App app = new App();
        BeanUtil.copyProperties(appUpdateRequest,app);
        // 2. 更新数据库
        int i = appMapper.updateById(app);
        ThrowUtils.throwIf(i != 1, ErrorCode.SYSTEM_ERROR,"更新失败，请重试");
        // 3. 更新ESRepo
        appESRepo.save(AppES.appToAppES(app));
        // 4. 更新Redis TODO
        return app.getId();
    }

    @Override
    public Long editApp(AppEditRequest appEditRequest) {
        // 1. 判断应用id与当前用户id是否一致
        Long userId = UserInfoUtil.getUserId();
        Long appUserId = appMapper.selectById(appEditRequest.getId()).getUserId();
        ThrowUtils.throwIf(!Objects.equals(userId, appUserId), ErrorCode.OPERATION_ERROR,"只能修改自己的应用");
        // 2. 更新
        AppUpdateRequest appUpdateRequest = new AppUpdateRequest();
        BeanUtil.copyProperties(appEditRequest,appUpdateRequest);
        return updateApp(appUpdateRequest);
    }

    @Override
    public Page<App> listPageApp(String all, Long userId, Integer appType, int current, int pageSize, Boolean dateAsc) {
        // 1. 根据条件从ESRepo中查询id列表

        // 1.1 构建分页条件
        ESSortBuilder esSortBuilder = new ESSortBuilder();
        Sort builder = esSortBuilder.bool(dateAsc).filed("createTime").builder();
        Pageable pageable = PageRequest.of(current, pageSize, builder);
        // 1.2 查询
        ESQueryBuilder eqb = new ESQueryBuilder();
        Page<AppES> appES = eqb
                .and(!StrUtil.isBlankIfStr(all), "appName", all)
                .and(userId != null, "userId", userId)
                .and(appType != null, "appType", appType)
                .get(AppES.class, elasticsearchTemplate, pageable);
        // 2. 根据id列表从Redis/数据库中取出数据

        // 2.1 数据库
        List<AppES> content = appES.getContent();
        List<Long> list = content.stream().map(AppES::getId).toList();
        List<App> apps = appMapper.selectBatchIds(list);

        // 3， 填入Page并返回
        return new PageImpl<>(apps,pageable,appES.getTotalElements());
    }

    @Override
    public Page<AppVO> listPageAppVO(String all, Long userId, Integer appType, int current, int pageSize, Boolean dateAsc) {
        // 1. 获取App page
        Page<App> appPage = this.listPageApp(all, userId, appType, current, pageSize, dateAsc);
        // 2. 将其中App List转为 AppVO List
        List<AppVO> list = appPage.getContent().stream().map(a -> {
            User user = userMapper.selectById(a.getUserId());
            return AppVO.getAppVOByApp(a, user);
        }).toList();
        // 3. 构建AppVO Page
        return new PageImpl<>(list,appPage.getPageable(),appPage.getTotalElements());
    }

}




